<?
// +----------------------------------------------------------------------
// | announce.php - MyPT
// +----------------------------------------------------------------------
// | Copyleft (c) 2010 By Asxzy All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: Asxzy <asxzy@163.com>
// +----------------------------------------------------------------------
define('THINK_PATH', './ThinkPHP');
ob_start("ob_gzhandler");

require_once("backend/bittorrent.php");
require_once("backend/benc.php");

function err($msg){
	benc_resp(array("failure reason" => array(type => "string", value => $msg)));
	exit();
}

function benc_resp($d){
	benc_resp_raw(benc(array(type => "dictionary", value => $d)));
}

function benc_resp_raw($x){
	header("Content-Type: text/plain");
	header("Pragma: no-cache");
	print($x);
}

foreach (array("passkey","info_hash","peer_id","event","ip", "localip") as $x){
	if(isset($_GET["$x"]))
	$GLOBALS[$x] = "" . $_GET[$x];
}

foreach (array("port","downloaded","uploaded","left") as $x)
	$GLOBALS[$x] = 0 + $_GET[$x];

if (strpos($passkey, "?")){
	$tmp = substr($passkey, strpos($passkey, "?"));
	$passkey = substr($passkey, 0, strpos($passkey, "?"));
	$tmpname = substr($tmp, 1, strpos($tmp, "=")-1);
	$tmpvalue = substr($tmp, strpos($tmp, "=")+1);
	$GLOBALS[$tmpname] = $tmpvalue;
}



foreach (array("passkey","info_hash","peer_id","port","downloaded","uploaded","left") as $x)
	if (!isset($x)) err("信息缺失 $x");

foreach (array("info_hash","peer_id") as $x)
	if (strlen($GLOBALS[$x]) != 20) err("无效的 $x (" . strlen($GLOBALS[$x]) . " - " . urlencode($GLOBALS[$x]) . ")");

if (strlen($passkey) != 32) err("无效的Passkey (" . strlen($passkey) . " - $passkey)");

$ip = getip();

$rsize = 50;
foreach(array("num want", "numwant", "num_want") as $k){
	if (isset($_GET[$k]))	{
		$rsize = 0 + $_GET[$k];
		break;
	}
}

// 处理info_hash,peer_id
if (strlen($info_hash) == 20)
    $info_hash = bin2hex($info_hash);
if (strlen($peer_id) == 20)
   	$peer_id = bin2hex($peer_id);

// Test information

$agent = $_SERVER["HTTP_USER_AGENT"];

// Deny access made with a browser...

if (preg_match("/^Mozilla\\//", $agent) || preg_match("/^Opera\\//", $agent) || preg_match("/^Links /", $agent) || preg_match("/^Lynx\\//", $agent))
	err("请用正确的BT客户端访问本服务器");

if (!$port || $port > 0xffff)
	err("无效端口");

if (!isset($event))
	$event = "";

$seeder = ($left == 0) ? "yes" : "no";

dbconn(false);

$valid = @mysql_fetch_row(@mysql_query("SELECT COUNT(*) FROM user WHERE passkey=" . sqlesc($passkey)));

if ($valid[0] != 1) err("无效的Passkey! 请重新下载种子");

$res = mysql_query("SELECT id, banned, seeders + leechers AS numpeers, UNIX_TIMESTAMP(added) AS ts FROM torrents WHERE " . hash_where("info_hash", $info_hash)) or err('服务器错误 : 5');

$torrent = mysql_fetch_assoc($res);
if (!$torrent)
	err("种子未上传,请先上传种子");

$torrentid = $torrent["id"];

$fields = "seeder, peer_id, ip, port, uploaded, downloaded, userid";

$numpeers = $torrent["numpeers"];
$limit = "";
if ($numpeers > $rsize)
	$limit = "ORDER BY RAND() LIMIT $rsize";
$res = mysql_query("SELECT $fields FROM peers WHERE torrent = $torrentid AND connectable = 'yes' $limit") or err('服务器错误 : 4');

$resp = "d" . benc_str("interval") . "i" . $announce_interval . "e" . benc_str("peers") . "l";
unset($self);
while ($row = mysql_fetch_assoc($res)){
	if ($row["peer_id"] === $peer_id)	{
		$userid = $row["userid"];
		$self = $row;
		continue;
	}

	$resp .= "d" .
		benc_str("ip") . benc_str($row["ip"]) .
		benc_str("peer id") . benc_str($row["peer_id"]) .
		benc_str("port") . "i" . $row["port"] . "e" .
		"e";
}

$resp .= "ee";

$selfwhere = "torrent = $torrentid AND " . hash_where("peer_id", $peer_id);

if (!isset($self)){
	$sql = "SELECT $fields FROM peers WHERE $selfwhere";
	$res = mysql_query($sql) or err('fout');
	$row = mysql_fetch_assoc($res);
	if ($row){
		$userid = $row["userid"];
		$self = $row;
	}
}


//// Up/down stats ////////////////////////////////////////////////////////////
if (!isset($self)){
	$valid = @mysql_fetch_row(@mysql_query("SELECT COUNT(*) FROM peers WHERE torrent=$torrentid AND passkey=" . sqlesc($passkey))) or err('mistake');
	if ($valid[0] >= 1 && $seeder == 'no') err("连接被限制.你只能用一个地方下载同一个种子");
	if ($valid[0] >= 3 && $seeder == 'yes') err("链接被限制");
	
	$rz = mysql_query("SELECT id, uploaded, downloaded, class FROM user WHERE passkey=".sqlesc($passkey)." AND enabled = 'yes' ORDER BY last_access DESC LIMIT 1") or err("服务器错误 : 2");
	if ($MEMBERSONLY && mysql_num_rows($rz) == 0) err("无效Passkey,请重新下载种子");
	$az = mysql_fetch_assoc($rz);
	$userid = $az["id"];

	if ($az["class"] < UC_VIP){
		$gigs = $az["uploaded"] / (1024*1024*1024);
		$elapsed = floor((strtotime("now") - $torrent["ts"]) / 3600);
		$ratio = (($az["downloaded"] > 0) ? ($az["uploaded"] / $az["downloaded"]) : 1);
		if ($ratio < 0.5 || $gigs < 5) $wait = 48;
		elseif ($ratio < 0.65 || $gigs < 6.5) $wait = 24;
		elseif ($ratio < 0.8 || $gigs < 8) $wait = 12;
		elseif ($ratio < 0.95 || $gigs < 9.5) $wait = 6;
		else $wait = 0;
		if ($elapsed < $wait)
				err("未授权 (" . ($wait - $elapsed) . "h) - 请阅读站点规则!");
	}
}else{
	$upthis = max(0, $uploaded - $self["uploaded"]);
	$downthis = max(0, $downloaded - $self["downloaded"]);

	if ($upthis > 0 || $downthis > 0)
		mysql_query("UPDATE user SET uploaded = uploaded + $upthis, downloaded = downloaded + $downthis WHERE id=$userid") or err("服务器错误 : 3");
}

///////////////////////////////////////////////////////////////////////////////

function portblacklisted($port){
	// direct connect
	if ($port >= 411 && $port <= 413) return true;

	// bittorrent
	if ($port >= 6881 && $port <= 6889) return true;

	// kazaa
	if ($port == 1214) return true;

	// gnutella
	if ($port >= 6346 && $port <= 6347) return true;

	// emule
	if ($port == 4662) return true;

	// winmx
	if ($port == 6699) return true;

	return false;
}

$updateset = array();

if ($event == "stopped"){
	if (isset($self))	{
		mysql_query("DELETE FROM peers WHERE $selfwhere");
		if (mysql_affected_rows()){
			if ($self["seeder"] == "yes"){
				mysql_query("UPDATE user SET now_upload = now_upload-1 WHERE id = $userid LIMIT 1");
				$updateset[] = "seeders = seeders - 1";
			}else{
				mysql_query("UPDATE user SET now_download = now_download-1 WHERE id = $userid LIMIT 1");
				$updateset[] = "leechers = leechers - 1";
			}
		}
	}
}else{
	if ($event == "completed"){
		$updateset[] = "times_completed = times_completed + 1";
		mysql_query("UPDATE user SET finish_times = finish_times+1 WHERE id = $userid LIMIT 1");
	}
	if (isset($self)){
		mysql_query("UPDATE peers SET uploaded = $uploaded, downloaded = $downloaded, to_go = $left, seeder = '$seeder'"
			. ($seeder == "yes" && $self["seeder"] != $seeder ? ", finishedat = " . time() : "") . " WHERE $selfwhere");
		if (mysql_affected_rows() && $self["seeder"] != $seeder){
			if ($seeder == "yes"){
				mysql_query("UPDATE user SET now_download = now_download-1 , now_upload = now_upload+1 WHERE id = $userid LIMIT 1");
				$updateset[] = "seeders = seeders + 1";
				$updateset[] = "leechers = leechers - 1";
			}else{
				mysql_query("UPDATE user SET now_download = now_download+1 , now_upload = now_upload-1 WHERE id = $userid LIMIT 1");
				$updateset[] = "seeders = seeders - 1";
				$updateset[] = "leechers = leechers + 1";
			}
		}
	}else{
		if (portblacklisted($port))
			err("端口 $port 不能被访问.");
		else{
			$sockres = @fsockopen($ip, $port, $errno, $errstr, 5);
			if (!$sockres)
				$connectable = "no";
			else{
				$connectable = "yes";
				@fclose($sockres);
			}
		}

$ret = mysql_query("INSERT INTO peers (connectable, torrent, peer_id, ip, port, uploaded, downloaded, to_go, started, seeder, userid, agent, uploadoffset, downloadoffset, passkey) VALUES ('$connectable', $torrentid, " . sqlesc($peer_id) . ", " . sqlesc($ip) . ", $port, $uploaded, $downloaded, $left, NOW(), '$seeder', $userid, " . sqlesc($agent) . ", $uploaded, $downloaded, " . sqlesc($passkey) . ")") or err('服务器错误');
		if ($ret){
			if ($seeder == "yes"){
				mysql_query("UPDATE user SET now_upload = now_upload+1 WHERE id = $userid LIMIT 1");
				$updateset[] = "seeders = seeders + 1";
			}else{
				mysql_query("UPDATE user SET now_download = now_download+1 WHERE id = $userid LIMIT 1");
				$updateset[] = "leechers = leechers + 1";
			}
		}
	}
}

if ($seeder == "yes"){
	if ($torrent["banned"] != "yes")
		$updateset[] = "visible = 'yes'";
}

if (count($updateset))
	mysql_query("UPDATE torrents SET " . join(",", $updateset) . " WHERE id = $torrentid");

print_r($resp);
benc_resp_raw($resp);

?>
